﻿using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _14块操作
{
    public static class BlockTool
    {
        /// <summary>
        /// 添加块表记录到图形数据库
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="btrName">块表记录名</param>
        /// <param name="ents">图形对象</param>
        /// <returns>ObjectId</returns>
        public static ObjectId AddBlockTableRecord(this Database db, string btrName, List<Entity> ents)
        {
            ObjectId btrId = ObjectId.Null;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (!bt.Has(btrName))
                {
                    BlockTableRecord btr = new BlockTableRecord();
                    btr.Name = btrName;
                    for (int i = 0; i < ents.Count; i++)
                    {
                        btr.AppendEntity(ents[i]);   
                    }
                    bt.UpgradeOpen();
                    bt.Add(btr);
                    trans.AddNewlyCreatedDBObject(btr, true);
                    bt.DowngradeOpen();
                }
                btrId = bt[btrName];
                trans.Commit();
            } 
            return btrId;
        }
        /// <summary>
        /// 向模型空间插入块参照
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="blockRecordId">块的ObjectId</param>
        /// <param name="position">插入位置</param>
        /// <returns>ObjectId</returns>
        public static ObjectId InsertBlockBlockReference(this Database db, ObjectId blockRecordId, Point3d position)
        {
            ObjectId blkReferId = ObjectId.Null;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (bt.Has(blockRecordId))
                {
                    //声明块参照
                    BlockReference br = new BlockReference(position, blockRecordId);
                    BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                    blkReferId = btr.AppendEntity(br);
                    trans.AddNewlyCreatedDBObject(br, true);
                }
                trans.Commit();
            }

            return blkReferId;
        }
        /// <summary>
        /// 向模型空间插入块参照
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="blockRecordId">块的ObjectId</param>
        /// <param name="position">插入位置</param>
        /// <param name="rotation">旋转角度</param>
        /// <param name="scale">缩放比例</param>
        /// <returns>ObjectId</returns>
        public static ObjectId InsertBlockBlockReference(this Database db, ObjectId blockRecordId, Point3d position,double rotation,Scale3d scale)
        {
            ObjectId blkReferId = ObjectId.Null;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (bt.Has(blockRecordId))
                {
                    BlockReference br = new BlockReference(position, blockRecordId);
                    br.Rotation = rotation;
                    br.ScaleFactors = scale;
                    BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                    blkReferId = btr.AppendEntity(br); 
                    trans.AddNewlyCreatedDBObject(br, true);
                }
                trans.Commit();
            }

            return blkReferId;
        }
        /// <summary>
        /// 向模型空间插入属性块参照
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="blockRecordId">块的ObjectId</param>
        /// <param name="position">插入位置</param>
        /// <param name="rotation">旋转角度</param>
        /// <param name="scale">缩放比例</param>
        /// <returns>ObjectId</returns>
        public static ObjectId InsertAttrBlockReference(this Database db, ObjectId blockRecordId, Point3d position, double rotation, Scale3d scale)
        {
            ObjectId blkReferId = ObjectId.Null;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (bt.Has(blockRecordId))
                {
                    //声明块参照
                    BlockReference br = new BlockReference(position, blockRecordId);
                    br.Rotation = rotation;
                    br.ScaleFactors = scale;
                    BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                    blkReferId = btr.AppendEntity(br);
                    //添加属性定义
                    BlockTableRecord blockRecord = (BlockTableRecord)blockRecordId.GetObject(OpenMode.ForRead);
                    if (blockRecord.HasAttributeDefinitions)
                    {
                        foreach (ObjectId item in blockRecord)
                        {
                            DBObject obj = item.GetObject(OpenMode.ForRead);
                            if (obj is AttributeDefinition)
                            {
                                //声明属性参照
                                AttributeReference attrRef = new AttributeReference();
                                attrRef.SetAttributeFromBlock((AttributeDefinition)obj, br.BlockTransform);
                                br.AttributeCollection.AppendAttribute(attrRef);
                                trans.AddNewlyCreatedDBObject(attrRef, true);
                            }
                        }
                    }
                    
                    trans.AddNewlyCreatedDBObject(br, true);
                }
                trans.Commit();
            }

            return blkReferId;
        }
        /// <summary>
        /// 更新块参照的属性
        /// </summary>
        /// <param name="BlockRefId">块参照的ObjectId</param>
        /// <param name="attrNameValues">属性字典</param>
        public static void UpdateBlockAttr(this ObjectId BlockRefId, Dictionary<string, string> attrNameValues)
        {
            using (Transaction trans = BlockRefId.Database.TransactionManager.StartTransaction())
            {
                if (BlockRefId != ObjectId.Null)
                {
                    BlockReference br = (BlockReference)BlockRefId.GetObject(OpenMode.ForRead);
                    foreach (ObjectId item in br.AttributeCollection)
                    {
                        AttributeReference attRef = (AttributeReference)item.GetObject(OpenMode.ForRead);
                        //判断属性字典中是否包含要更改的属性值
                        if (attrNameValues.ContainsKey(attRef.Tag.ToString()))
                        {
                            attRef.UpgradeOpen();
                            attRef.TextString = attrNameValues[attRef.Tag.ToString()].ToString();
                            attRef.DowngradeOpen();
                        }
                    }
                }
                trans.Commit();
            }
        }
    }
}
